﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using MazeBuilder.Entities.Tiles;
using System.ComponentModel.Composition;
using System.Linq;
using RoomModuleCatalog;

namespace MazeBuilder
{
  
  public static class RoomFactory
  {
    private static Tile[][] tiles;
    private static AggregateCatalog roomModuleCatalog;
    private static CompositionContainer roomModuleContainer;
    [ImportMany(AllowRecomposition = true)]
    public static List<Lazy<IModuleExpression>> ModuleExpressions { get; set; }

    public static RoomDefinition GetRoomDefinition(int i, int mi, int j, int mj, int roomCounter) {
      var result = new RoomDefinition();
      LoadRoomModuleCatalog();
      ModuleExpressions = roomModuleContainer.GetExports<IModuleExpression>().ToList();
      var seed = ModuleExpressions[StaticRandomNumberGenerator.Next(0, ModuleExpressions.Count)];

      tiles = new Tile[mi - i][];
      var currentI = i;
      for (var k = 0; k < tiles.Length; k++) {
        tiles[k] = new Tile[mj - j];
        var currentJ = j;
        var incrementI = false;
        for (var l = 0; l < tiles[k].Length; l++) {
#if !DEBUG
          if (roomCounter > 1)
          {
#endif
            Tile tile;
            if (GetModuleExpression(seed.Value, k, l, out tile))
            {
              tile.Row = currentI;
              tile.Col = currentJ;
              tiles[k][l] = tile;
            }
            else
              tiles[k][l] = new FloorTile(currentI, currentJ);
#if !DEBUG
          }
          else
            tiles[k][l] = new FloorTile(currentI, currentJ);
#endif
          currentJ++;
          incrementI = true;
        }
        if (incrementI)
          currentI++;
      }
      result.Definition = tiles;
      return result;
    }

    private static void LoadRoomModuleCatalog() {
      if (roomModuleCatalog == null)
        // todo: load module from directory by config path
        roomModuleCatalog = new AggregateCatalog(new DirectoryCatalog("."));
      roomModuleContainer = new CompositionContainer(roomModuleCatalog);
    }

    private static bool GetModuleExpression(IModuleExpression module, int k, int l, out Tile tile) {
      var expression = module.getExpressionResult(k, l);
      tile = module.getTile(k, l);

      return expression;
    }
  }

}
